#include "wxscolourproperty.h"
#include <logmanager.h>
#include <wx/settings.h>
#include <wx/colordlg.h>
#include <wx/dc.h>
#include "../wxsflags.h"
#include <wx/odcombo.h>

using namespace wxsFlags;

namespace {
  static const wxChar* wxsColourLabels[] = {
    _T( "Default" ),
    _T( "Custom" ),
    _T( "Scrollbar" ),
    _T( "Desktop" ),
    _T( "Active window caption" ),
    _T( "Inactive window caption" ),
    _T( "Menu background" ),
    _T( "Window background" ),
    _T( "Window frame" ),
    _T( "Menu text" ),
    _T( "Text in window" ),
    _T( "Text in window caption" ),
    _T( "Active window border" ),
    _T( "Inactive window border" ),
    _T( "Background for MDI apps" ),
    _T( "Selected item" ),
    _T( "Text of selected item" ),
    _T( "Face of button" ),
    _T( "Edge of button" ),
    _T( "Grayed (disabled) text" ),
    _T( "Text on buttons" ),
    _T( "Text of inactive caption" ),
    _T( "Highlight colour for buttons" ),
    _T( "Dark shadow for 3D items" ),
    _T( "Light for 3D items" ),
    _T( "Tooltip text" ),
    _T( "Tooltip background" ),
    _T( "Listbox" ),
    _T( "Hot light" ),
    _T( "Gradient of active caption" ),
    _T( "Gradnent of inactive caption" ),
    _T( "Selected menu item" ),
    _T( "Menu bar" ),
    0
  };

  const int wxsColourCount = ( sizeof( wxsColourLabels ) / sizeof( wxsColourLabels[0] ) ) - 1;

  static const long wxsColourValues[] = {
    wxsCOLOUR_DEFAULT,
    wxPG_COLOUR_CUSTOM,
    wxSYS_COLOUR_SCROLLBAR,
    wxSYS_COLOUR_DESKTOP,
    wxSYS_COLOUR_ACTIVECAPTION,
    wxSYS_COLOUR_INACTIVECAPTION,
    wxSYS_COLOUR_MENU,
    wxSYS_COLOUR_WINDOW,
    wxSYS_COLOUR_WINDOWFRAME,
    wxSYS_COLOUR_MENUTEXT,
    wxSYS_COLOUR_WINDOWTEXT,
    wxSYS_COLOUR_CAPTIONTEXT,
    wxSYS_COLOUR_ACTIVEBORDER,
    wxSYS_COLOUR_INACTIVEBORDER,
    wxSYS_COLOUR_APPWORKSPACE,
    wxSYS_COLOUR_HIGHLIGHT,
    wxSYS_COLOUR_HIGHLIGHTTEXT,
    wxSYS_COLOUR_BTNFACE,
    wxSYS_COLOUR_BTNSHADOW,
    wxSYS_COLOUR_GRAYTEXT,
    wxSYS_COLOUR_BTNTEXT,
    wxSYS_COLOUR_INACTIVECAPTIONTEXT,
    wxSYS_COLOUR_BTNHIGHLIGHT,
    wxSYS_COLOUR_3DDKSHADOW,
    wxSYS_COLOUR_3DLIGHT,
    wxSYS_COLOUR_INFOTEXT,
    wxSYS_COLOUR_INFOBK,
    wxSYS_COLOUR_LISTBOX,
    wxSYS_COLOUR_HOTLIGHT,
    wxSYS_COLOUR_GRADIENTACTIVECAPTION,
    wxSYS_COLOUR_GRADIENTINACTIVECAPTION,
    wxSYS_COLOUR_MENUHILIGHT,
    wxSYS_COLOUR_MENUBAR,
    0
  };

  static wxPGChoices gs_wxsColourProperty_choicesCache;


  class wxsMyColourPropertyClass : public wxEnumProperty {
      WX_PG_DECLARE_PROPERTY_CLASS( wxsMyColourPropertyClass )
    public:

      wxsMyColourPropertyClass( const wxString& label = wxEmptyString,
                                const wxString& name = wxPG_LABEL,
                                const wxColourPropertyValue& value = wxColourPropertyValue( wxsCOLOUR_DEFAULT, *wxWHITE ) );
      ~wxsMyColourPropertyClass();
      virtual void OnSetValue();
      virtual bool IntToValue( wxVariant& variant, int number, int argFlags = 0 ) const;
      virtual wxString ColourToString( const wxColour& col, int index ) const;
      virtual int GetCustomColourIndex() const;

      WX_PG_DECLARE_BASIC_TYPE_METHODS()
      WX_PG_DECLARE_EVENT_METHODS()
      WX_PG_DECLARE_ATTRIBUTE_METHODS()

      WX_PG_DECLARE_CUSTOM_PAINT_METHODS()

      bool QueryColourFromUser( wxVariant& variant ) const;


      virtual wxColour GetColour( int index ) const;

      wxColourPropertyValue GetVal( const wxVariant* pVariant = NULL ) const;

    protected:

      void Init( int type, const wxColour& colour );


      virtual wxVariant DoTranslateVal( wxColourPropertyValue& v ) const;
      wxVariant TranslateVal( wxColourPropertyValue& v ) const {
        return DoTranslateVal( v );
      }
      wxVariant TranslateVal( int type, const wxColour& colour ) const {
        wxColourPropertyValue v( type, colour );
        return DoTranslateVal( v );
      }


      int ColToInd( const wxColour& colour ) const;
  };

  WX_PG_IMPLEMENT_PROPERTY_CLASS( wxsMyColourPropertyClass, wxEnumProperty,
                                  wxColourPropertyValue, const wxColourPropertyValue&, Choice )

  void wxsMyColourPropertyClass::Init( int type, const wxColour& colour ) {
    wxColourPropertyValue cpv;
    if( colour.Ok() ) {
      cpv.Init( type, colour );
    } else
    { cpv.Init( type, *wxWHITE ); }
    m_flags |= wxPG_PROP_STATIC_CHOICES;
    m_value = wxColourPropertyValueToVariant( cpv );
    OnSetValue();
  }

  wxsMyColourPropertyClass::wxsMyColourPropertyClass( const wxString& label, const wxString& name,
      const wxColourPropertyValue& value )
    : wxEnumProperty( label, name, wxsColourLabels, wxsColourValues, &gs_wxsColourProperty_choicesCache ) {
    Init( value.m_type, value.m_colour );
  }

  wxsMyColourPropertyClass::~wxsMyColourPropertyClass() { }


  wxColourPropertyValue wxsMyColourPropertyClass::GetVal( const wxVariant* pVariant ) const {
    if( !pVariant ) {
      pVariant = &m_value;
    }
    if( pVariant->IsNull() ) {
      return wxColourPropertyValue( wxPG_COLOUR_UNSPECIFIED, wxColour() );
    }
    wxColourPropertyValue* v1 = &wxColourPropertyValueFromVariant( *pVariant );
    if( v1 ) {
      return *v1;
    }
    wxColour* pCol = wxGetVariantCast( *pVariant, wxColour );
    wxColour col;
    if( pCol ) {
      col = *pCol;
    } else
    { col << *pVariant; }
    wxColourPropertyValue v2( wxPG_COLOUR_CUSTOM, col );
    int colInd = ColToInd( col );
    if( colInd != wxNOT_FOUND ) {
      v2.m_type = colInd;
    }
    return v2;
  }

  wxVariant wxsMyColourPropertyClass::DoTranslateVal( wxColourPropertyValue& v ) const {
    return wxColourPropertyValueToVariant( v );
  }

  int wxsMyColourPropertyClass::ColToInd( const wxColour& colour ) const {
    size_t i;
    size_t i_max = m_choices.GetCount();
    for( i = 0; i < i_max; i++ ) {
      int ind = m_choices[i].GetValue();
      if( colour == GetColour( ind ) ) {
        return ind;
      }
    }
    return wxNOT_FOUND;
  }
  static inline wxColour wxColourFromPGLong( long col ) {
    return wxColour( ( col & 0xFF ), ( ( col >> 8 ) & 0xFF ), ( ( col >> 16 ) & 0xFF ) );
  }
  void wxsMyColourPropertyClass::OnSetValue() {
    if( wxPGIsVariantType( m_value, wxobject ) ) {
      wxASSERT( m_value.IsValueKindOf( CLASSINFO( wxColour ) ) );
      wxColour* pCol = ( wxColour* ) m_value.GetWxObjectPtr();
      m_value << *pCol;
    }
    wxColourPropertyValue val = GetVal( &m_value );
    if( val.m_type == wxPG_COLOUR_UNSPECIFIED ) {
      m_value.MakeNull();
      return;
    } else {
      if( val.m_type < wxPG_COLOUR_WEB_BASE ) {
        val.m_colour = GetColour( val.m_type );
      }
      m_value = TranslateVal( val );
    }
    wxColourPropertyValue* pCpv = &wxColourPropertyValueFromVariant( m_value );
    wxColour col;
    if( pCpv ) {
      col = pCpv->m_colour;
    } else
    { col << m_value; }
    if( !col.Ok() ) {
      SetValueToUnspecified();
      SetIndex( wxNOT_FOUND );
      return;
    }
    int ind;
    if( pCpv ) {
      if( pCpv->m_type < wxPG_COLOUR_WEB_BASE ) {
        ind = GetIndexForValue( pCpv->m_type );
      } else if( pCpv->m_type == wxPG_COLOUR_CUSTOM ) {
        ind = GetCustomColourIndex();
      } else {
        pCpv->m_type = wxsCOLOUR_DEFAULT;
        ind = 0;
      }
    } else {
      ind = ColToInd( col );
      if( ind == wxNOT_FOUND ) {
        ind = GetCustomColourIndex();
      }
    }
    SetIndex( ind );
  }

  wxColour wxsMyColourPropertyClass::GetColour( int index ) const {
    return wxSystemSettings::GetColour( ( wxSystemColour )index );
  }

  wxString wxsMyColourPropertyClass::ColourToString( const wxColour& col,
      int index ) const {
    if( index == wxNOT_FOUND ) {
      return F( wxT( "(%i,%i,%i)" ), ( int )col.Red(), ( int )col.Green(), ( int )col.Blue() );
    } else {
      return m_choices.GetLabel( index );
    }
  }

  wxString wxsMyColourPropertyClass::GetValueAsString( M_Code_unused int argFlags ) const {
    wxColourPropertyValue val = GetVal();
    int ind = GetIndex();
    if( val.m_type == wxPG_COLOUR_CUSTOM ) {
      ind = wxNOT_FOUND;
    }
    if( val.m_type == wxsCOLOUR_DEFAULT ) {
      return wxsColourLabels[ind];
    }
    return ColourToString( val.m_colour, ind );
  }

  wxSize wxsMyColourPropertyClass::OnMeasureImage( int ) const {
    return wxPG_DEFAULT_IMAGE_SIZE;
  }


  int wxsMyColourPropertyClass::GetCustomColourIndex() const {
    for( size_t i = 0; m_choices.GetCount(); ++i ) {
      if( m_choices[i].GetValue() == wxPG_COLOUR_CUSTOM ) {
        return i;
      }
    }
    return -1;
  }


  bool wxsMyColourPropertyClass::QueryColourFromUser( wxVariant& variant ) const {
    wxASSERT( m_value.GetType() != wxT( "string" ) );
    bool res = false;
    wxPropertyGrid* propgrid = GetGrid();
    wxASSERT( propgrid );
    if( !( propgrid->GetInternalFlags() & wxPG_FL_IN_ONCUSTOMEDITOREVENT ) )
    { return res; }
    wxColourPropertyValue val = GetVal();
    val.m_type = wxPG_COLOUR_CUSTOM;
    wxColourData data;
    data.SetChooseFull( true );
    data.SetColour( val.m_colour );
    int i;
    for( i = 0; i < 16; i++ ) {
      wxColour colour( i * 16, i * 16, i * 16 );
      data.SetCustomColour( i, colour );
    }
    wxColourDialog dialog( propgrid, &data );
    if( dialog.ShowModal() == wxID_OK ) {
      wxColourData retData = dialog.GetColourData();
      val.m_colour = retData.GetColour();
      variant = DoTranslateVal( val );
      SetValueInEvent( variant );
      res = true;
    }
    return res;
  }

  bool wxsMyColourPropertyClass::IntToValue( wxVariant& variant, int number, int ( argFlags ) ) const {
    int index = number;
    int type = GetValueForIndex( index );
    if( type == wxPG_COLOUR_CUSTOM ) {
      QueryColourFromUser( variant );
    } else {
      variant = TranslateVal( type, GetColour( type ) );
    }
    return true;
  }

  bool wxsMyColourPropertyClass::OnEvent( wxPropertyGrid* propgrid, wxWindow * ( primary ), wxEvent& event ) {
    bool askColour = false;
    if( propgrid->IsMainButtonEvent( event ) ) {
      askColour = true;
    } else if( event.GetEventType() == wxEVT_COMMAND_COMBOBOX_SELECTED ) {
      wxPGOwnerDrawnComboBox* cb = ( wxPGOwnerDrawnComboBox* )propgrid->GetEditorControl();
      if( cb ) {
        int index = cb->GetSelection();
        if( index == GetCustomColourIndex() ) {
          askColour = true;
        }
      }
    }
    if( askColour && !propgrid->WasValueChangedInEvent() ) {
      wxVariant variant;
      if( QueryColourFromUser( variant ) ) {
        return true;
      }
    }
    return false;
  }

  void wxsMyColourPropertyClass::OnCustomPaint( wxDC& dc, const wxRect& rect, wxPGPaintData& paintdata ) {
    int value;
    if( paintdata.m_choiceItem >= 0 && paintdata.m_choiceItem < ( int )( GetItemCount() ) ) {
      int index = paintdata.m_choiceItem;
      value = wxsColourValues[index];
    } else if( !( m_flags & wxPG_PROP_UNSPECIFIED ) ) {
      value = GetVal().m_type;
    } else {
      dc.SetBrush( *wxWHITE );
      dc.DrawRectangle( rect );
      return;
    }
    if( value == wxsCOLOUR_DEFAULT ) {
      dc.SetBrush( *wxWHITE );
      dc.DrawRectangle( rect );
      dc.SetBrush( wxBrush( *wxBLACK, wxBDIAGONAL_HATCH ) );
      dc.DrawRectangle( rect );
      return;
    }
    if( value == wxPG_COLOUR_CUSTOM ) {
      dc.SetBrush( GetVal().m_colour );
    } else {
      dc.SetBrush( wxSystemSettings::GetColour( ( wxSystemColour )value ) );
    }
    dc.DrawRectangle( rect );
  }


  bool wxsMyColourPropertyClass::StringToValue( wxVariant& value, const wxString& text, int argFlags ) const {
    wxString colourName;
    wxString colourRGB;
    int ppos = text.Find( wxT( "(" ) );
    if( ppos == wxNOT_FOUND ) {
      colourName = text;
    } else {
      colourName = text.substr( 0, ppos );
      colourRGB = text.substr( ppos, text.length() - ppos );
    }
    colourName.Trim( true );
    colourName.Trim( false );
    colourRGB.Trim( true );
    if( colourRGB.length() < 7 ) {
      colourRGB.clear();
    }
    if( colourRGB.length() == 0 && m_choices.GetCount() &&
        colourName == m_choices.GetLabel( GetCustomColourIndex() ) ) {
      if( !( argFlags & wxPG_EDITABLE_VALUE ) ) {
        ResetNextIndex();
        return false;
      }
      QueryColourFromUser( value );
    } else {
      wxColourPropertyValue val;
      bool done = false;
      if( colourName.length() ) {
        bool res = wxEnumProperty::StringToValue( value, colourName, argFlags );
        if( res && GetIndex() >= 0 ) {
          val.m_type = GetIndex();
          if( val.m_type < m_choices.GetCount() ) {
            val.m_type = m_choices[val.m_type].GetValue();
          }
          val.m_colour = GetColour( val.m_type );
          done = true;
        }
      }
      if( colourRGB.length() && !done ) {
        val.m_type = wxPG_COLOUR_CUSTOM;
        int r = -1, g = -1, b = -1;
        wxSscanf( colourRGB.c_str(), wxT( "(%i,%i,%i)" ), &r, &g, &b );
        if( r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 ) {
          val.m_colour.Set( r, g, b );
          done = true;
        }
      }
      if( !done ) {
        ResetNextIndex();
        return false;
      }
      value = DoTranslateVal( val );
    }
    return true;
  }

  bool wxsMyColourPropertyClass::DoSetAttribute( M_Code_unused const wxString& name, M_Code_unused wxVariant& value ) {
    return false;
  }
}

wxColour wxsColourData::GetColour() {
  if( m_type == wxsCOLOUR_DEFAULT ) {
    return wxColour();
  }
  if( m_type == wxPG_COLOUR_CUSTOM ) {
    return m_colour;
  }
  return wxSystemSettings::GetColour( ( wxSystemColour )m_type );
}

wxString wxsColourData::BuildCode( wxsCoderContext* Context ) {
  if( m_type == wxsCOLOUR_DEFAULT ) {
    return wxEmptyString;
  }
  switch( Context->m_Language ) {
    case wxsCPP: {
      if( m_type == wxPG_COLOUR_CUSTOM ) {
        return F( _T( "wxColour(%u,%u,%u)" ), ( unsigned int )m_colour.Red(), ( unsigned int )m_colour.Green(),
                  ( unsigned int )m_colour.Blue() );
      }
      wxString SysColName;
#define SYSCLR(N) if ( m_type == N ) SysColName = _T(#N); else
      SYSCLR( wxSYS_COLOUR_SCROLLBAR )
      SYSCLR( wxSYS_COLOUR_BACKGROUND )
      SYSCLR( wxSYS_COLOUR_DESKTOP )
      SYSCLR( wxSYS_COLOUR_ACTIVECAPTION )
      SYSCLR( wxSYS_COLOUR_INACTIVECAPTION )
      SYSCLR( wxSYS_COLOUR_MENU )
      SYSCLR( wxSYS_COLOUR_WINDOW )
      SYSCLR( wxSYS_COLOUR_WINDOWFRAME )
      SYSCLR( wxSYS_COLOUR_MENUTEXT )
      SYSCLR( wxSYS_COLOUR_WINDOWTEXT )
      SYSCLR( wxSYS_COLOUR_CAPTIONTEXT )
      SYSCLR( wxSYS_COLOUR_ACTIVEBORDER )
      SYSCLR( wxSYS_COLOUR_INACTIVEBORDER )
      SYSCLR( wxSYS_COLOUR_APPWORKSPACE )
      SYSCLR( wxSYS_COLOUR_HIGHLIGHT )
      SYSCLR( wxSYS_COLOUR_HIGHLIGHTTEXT )
      SYSCLR( wxSYS_COLOUR_BTNFACE )
      SYSCLR( wxSYS_COLOUR_3DFACE )
      SYSCLR( wxSYS_COLOUR_BTNSHADOW )
      SYSCLR( wxSYS_COLOUR_3DSHADOW )
      SYSCLR( wxSYS_COLOUR_GRAYTEXT )
      SYSCLR( wxSYS_COLOUR_BTNTEXT )
      SYSCLR( wxSYS_COLOUR_INACTIVECAPTIONTEXT )
      SYSCLR( wxSYS_COLOUR_BTNHIGHLIGHT )
      SYSCLR( wxSYS_COLOUR_BTNHILIGHT )
      SYSCLR( wxSYS_COLOUR_3DHIGHLIGHT )
      SYSCLR( wxSYS_COLOUR_3DHILIGHT )
      SYSCLR( wxSYS_COLOUR_3DDKSHADOW )
      SYSCLR( wxSYS_COLOUR_3DLIGHT )
      SYSCLR( wxSYS_COLOUR_INFOTEXT )
      SYSCLR( wxSYS_COLOUR_INFOBK )
      SYSCLR( wxSYS_COLOUR_LISTBOX )
      SYSCLR( wxSYS_COLOUR_HOTLIGHT )
      SYSCLR( wxSYS_COLOUR_GRADIENTACTIVECAPTION )
      SYSCLR( wxSYS_COLOUR_GRADIENTINACTIVECAPTION )
      SYSCLR( wxSYS_COLOUR_MENUHILIGHT )
      SYSCLR( wxSYS_COLOUR_MENUBAR ) {}
#undef SYSCLR
      if( SysColName.empty() ) {
        return wxEmptyString;
      }
      Context->AddHeader( _T( "<wx/settings.h>" ), _T( "" ), hfLocal );
      return _T( "wxSystemSettings::GetColour(" ) + SysColName + _T( ")" );
    }
    case wxsUnknownLanguage:
    default: {
      wxsCodeMarks::Unknown( _T( "wxsColourData::BuildCode" ), Context->m_Language );
    }
  }
  return wxEmptyString;
}

#define VALUE   wxsVARIABLE(Object,ValueOffset,wxsColourData)


wxsColourProperty::wxsColourProperty( const wxString& PGName, const wxString& DataName, long _ValueOffset, int Priority ):
  wxsProperty( PGName, DataName, Priority ), ValueOffset( _ValueOffset ) {}


void wxsColourProperty::PGCreate( wxsPropertyContainer* Object, wxPropertyGridManager* Grid, wxPGId Parent ) {
  PGRegister( Object, Grid, Grid->AppendIn( Parent, new wxsMyColourPropertyClass( GetPGName(), wxPG_LABEL, VALUE ) ) );
}

bool wxsColourProperty::PGRead( wxsPropertyContainer* Object, wxPropertyGridManager* Grid,
                                wxPGId Id, M_Code_unused long Index ) {
  wxVariant value = Grid->GetPropertyValue( Id );
  wxColourPropertyValue* Val = wxGetVariantCast( value, wxColourPropertyValue );
  if( !Val ) {
    return false;
  }
  VALUE = *Val;
  return true;
}

bool wxsColourProperty::PGWrite( M_Code_unused wxsPropertyContainer* Object, M_Code_unused wxPropertyGridManager* Grid,
                                 M_Code_unused wxPGId Id, M_Code_unused long Index ) {
  return true;
}

bool wxsColourProperty::XmlRead( wxsPropertyContainer* Object, TiXmlElement* Element ) {
  if( !Element ) {
    VALUE.m_type = wxsCOLOUR_DEFAULT;
    VALUE.m_colour = wxColour( 0, 0, 0 );
    return false;
  }
  wxString Str;
  if( !XmlGetString( Element, Str ) || Str.empty() ) {
    VALUE.m_type = wxsCOLOUR_DEFAULT;
    VALUE.m_colour = wxColour( 0, 0, 0 );
    return false;
  }
  unsigned long tmp = 0;
  if( Str.Length() == 7 && Str[0] == _T( '#' ) && wxSscanf( Str.c_str(), _T( "#%lX" ), &tmp ) == 1 ) {
    VALUE.m_type = wxPG_COLOUR_CUSTOM;
    VALUE.m_colour = wxColour( ( unsigned char )( ( tmp & 0xFF0000 ) >> 16 ), ( unsigned char )( ( tmp & 0x00FF00 ) >> 8 ),
                               ( unsigned char )( ( tmp & 0x0000FF ) ) );
  } else {
#define SYSCLR(N) if ( Str == _T(#N) ) { VALUE.m_type = N; VALUE.m_colour = wxSystemSettings::GetColour(N); } else
    SYSCLR( wxSYS_COLOUR_SCROLLBAR )
    SYSCLR( wxSYS_COLOUR_BACKGROUND )
    SYSCLR( wxSYS_COLOUR_DESKTOP )
    SYSCLR( wxSYS_COLOUR_ACTIVECAPTION )
    SYSCLR( wxSYS_COLOUR_INACTIVECAPTION )
    SYSCLR( wxSYS_COLOUR_MENU )
    SYSCLR( wxSYS_COLOUR_WINDOW )
    SYSCLR( wxSYS_COLOUR_WINDOWFRAME )
    SYSCLR( wxSYS_COLOUR_MENUTEXT )
    SYSCLR( wxSYS_COLOUR_WINDOWTEXT )
    SYSCLR( wxSYS_COLOUR_CAPTIONTEXT )
    SYSCLR( wxSYS_COLOUR_ACTIVEBORDER )
    SYSCLR( wxSYS_COLOUR_INACTIVEBORDER )
    SYSCLR( wxSYS_COLOUR_APPWORKSPACE )
    SYSCLR( wxSYS_COLOUR_HIGHLIGHT )
    SYSCLR( wxSYS_COLOUR_HIGHLIGHTTEXT )
    SYSCLR( wxSYS_COLOUR_BTNFACE )
    SYSCLR( wxSYS_COLOUR_3DFACE )
    SYSCLR( wxSYS_COLOUR_BTNSHADOW )
    SYSCLR( wxSYS_COLOUR_3DSHADOW )
    SYSCLR( wxSYS_COLOUR_GRAYTEXT )
    SYSCLR( wxSYS_COLOUR_BTNTEXT )
    SYSCLR( wxSYS_COLOUR_INACTIVECAPTIONTEXT )
    SYSCLR( wxSYS_COLOUR_BTNHIGHLIGHT )
    SYSCLR( wxSYS_COLOUR_BTNHILIGHT )
    SYSCLR( wxSYS_COLOUR_3DHIGHLIGHT )
    SYSCLR( wxSYS_COLOUR_3DHILIGHT )
    SYSCLR( wxSYS_COLOUR_3DDKSHADOW )
    SYSCLR( wxSYS_COLOUR_3DLIGHT )
    SYSCLR( wxSYS_COLOUR_INFOTEXT )
    SYSCLR( wxSYS_COLOUR_INFOBK )
    SYSCLR( wxSYS_COLOUR_LISTBOX )
    SYSCLR( wxSYS_COLOUR_HOTLIGHT )
    SYSCLR( wxSYS_COLOUR_GRADIENTACTIVECAPTION )
    SYSCLR( wxSYS_COLOUR_GRADIENTINACTIVECAPTION )
    SYSCLR( wxSYS_COLOUR_MENUHILIGHT )
    SYSCLR( wxSYS_COLOUR_MENUBAR ) {
      VALUE.m_type = wxsCOLOUR_DEFAULT;
      VALUE.m_colour = wxColour( 0, 0, 0 );
    }
#undef SYSCLR
  }
  return true;
}

bool wxsColourProperty::XmlWrite( wxsPropertyContainer* Object, TiXmlElement* Element ) {
  if( VALUE.m_type == wxsCOLOUR_DEFAULT ) {
    return false;
  }
  if( VALUE.m_type == wxPG_COLOUR_CUSTOM ) {
    XmlSetString( Element, F( _T( "#%02X%02X%02X" ), ( unsigned int )VALUE.m_colour.Red(),
                              ( unsigned int )VALUE.m_colour.Green(), ( unsigned int )VALUE.m_colour.Blue() ) );
    return true;
  }
#define SYSCLR(N) if ( VALUE.m_type == N ) XmlSetString(Element,_T(#N)); else
  SYSCLR( wxSYS_COLOUR_SCROLLBAR )
  SYSCLR( wxSYS_COLOUR_BACKGROUND )
  SYSCLR( wxSYS_COLOUR_DESKTOP )
  SYSCLR( wxSYS_COLOUR_ACTIVECAPTION )
  SYSCLR( wxSYS_COLOUR_INACTIVECAPTION )
  SYSCLR( wxSYS_COLOUR_MENU )
  SYSCLR( wxSYS_COLOUR_WINDOW )
  SYSCLR( wxSYS_COLOUR_WINDOWFRAME )
  SYSCLR( wxSYS_COLOUR_MENUTEXT )
  SYSCLR( wxSYS_COLOUR_WINDOWTEXT )
  SYSCLR( wxSYS_COLOUR_CAPTIONTEXT )
  SYSCLR( wxSYS_COLOUR_ACTIVEBORDER )
  SYSCLR( wxSYS_COLOUR_INACTIVEBORDER )
  SYSCLR( wxSYS_COLOUR_APPWORKSPACE )
  SYSCLR( wxSYS_COLOUR_HIGHLIGHT )
  SYSCLR( wxSYS_COLOUR_HIGHLIGHTTEXT )
  SYSCLR( wxSYS_COLOUR_BTNFACE )
  SYSCLR( wxSYS_COLOUR_3DFACE )
  SYSCLR( wxSYS_COLOUR_BTNSHADOW )
  SYSCLR( wxSYS_COLOUR_3DSHADOW )
  SYSCLR( wxSYS_COLOUR_GRAYTEXT )
  SYSCLR( wxSYS_COLOUR_BTNTEXT )
  SYSCLR( wxSYS_COLOUR_INACTIVECAPTIONTEXT )
  SYSCLR( wxSYS_COLOUR_BTNHIGHLIGHT )
  SYSCLR( wxSYS_COLOUR_BTNHILIGHT )
  SYSCLR( wxSYS_COLOUR_3DHIGHLIGHT )
  SYSCLR( wxSYS_COLOUR_3DHILIGHT )
  SYSCLR( wxSYS_COLOUR_3DDKSHADOW )
  SYSCLR( wxSYS_COLOUR_3DLIGHT )
  SYSCLR( wxSYS_COLOUR_INFOTEXT )
  SYSCLR( wxSYS_COLOUR_INFOBK )
  SYSCLR( wxSYS_COLOUR_LISTBOX )
  SYSCLR( wxSYS_COLOUR_HOTLIGHT )
  SYSCLR( wxSYS_COLOUR_GRADIENTACTIVECAPTION )
  SYSCLR( wxSYS_COLOUR_GRADIENTINACTIVECAPTION )
  SYSCLR( wxSYS_COLOUR_MENUHILIGHT )
  SYSCLR( wxSYS_COLOUR_MENUBAR ) {
    return false;
  }
#undef SYSCLR
  return true;
}

bool wxsColourProperty::PropStreamRead( wxsPropertyContainer* Object, wxsPropertyStream* Stream ) {
  bool Ret = true;
  long Colour;
  unsigned long Type;
  Stream->SubCategory( GetDataName() );
  if( !Stream->GetULong( _T( "type" ), Type, wxsCOLOUR_DEFAULT ) ) {
    Ret = false;
  }
  VALUE.m_type = Type;
  if( !Stream->GetLong( _T( "value" ), Colour, 0 ) ) {
    Ret = false;
  }
  if( Type == wxsCOLOUR_DEFAULT ) {
    VALUE.m_colour = wxColour( 0, 0, 0 );
  } else if( Type == wxPG_COLOUR_CUSTOM ) {
    VALUE.m_colour = Colour;
  } else {
    VALUE.m_colour = wxSystemSettings::GetColour( ( wxSystemColour )VALUE.m_type );
  }
  Stream->PopCategory();
  return Ret;
}

bool wxsColourProperty::PropStreamWrite( wxsPropertyContainer* Object, wxsPropertyStream* Stream ) {
  bool Ret = true;
  long Colour = ( ( unsigned int )VALUE.m_colour.Red()   << 16 ) |
                ( ( unsigned int )VALUE.m_colour.Green() <<  8 ) | ( ( unsigned int )VALUE.m_colour.Blue() );
  unsigned long Type = VALUE.m_type;
  Stream->SubCategory( GetDataName() );
  if( !Stream->PutULong( _T( "type" ), Type, wxsCOLOUR_DEFAULT ) ) {
    Ret = false;
  }
  VALUE.m_type = Type;
  if( !Stream->PutLong( _T( "value" ), Colour, 0 ) ) {
    Ret = false;
  }
  if( VALUE.m_type == wxsCOLOUR_DEFAULT ) {
    VALUE.m_colour = wxColour( 0, 0, 0 );
  } else if( VALUE.m_type == wxPG_COLOUR_CUSTOM ) {
    VALUE.m_colour = Colour;
  } else {
    VALUE.m_colour = wxSystemSettings::GetColour( ( wxSystemColour )VALUE.m_type );
  }
  Stream->PopCategory();
  return Ret;
}
